﻿#region Using directives

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;

using Weazel.Toad.Application.Forms;
using Weazel.Toad.Application.Items;
using Weazel.Toad.Application.Actions;

#endregion

namespace Weazel.Toad.Application
{
  /// <summary>
  /// This singleton represents
  /// the instance of the running
  /// application
  /// </summary> 
  public class Application 
  {
    #region Appliation events

    public event EventHandler<SelectedItemChangedEventArgs> SelectedItemChanging;
    public event EventHandler<SelectedItemChangedEventArgs> SelectedItemChanged;

		public event EventHandler<ItemOpenedOrClosedEventArgs> ItemOpened;
		public event EventHandler<ItemOpenedOrClosedEventArgs> ItemClosed;

    #endregion

    /// <summary>
    /// Singleton instance
    /// </summary>
    private static readonly Application instance = new Application();

    /// <summary>
    /// Singleton accessor
    /// </summary>
    /// <value></value>
    public static Application Instance
    {
      get { return instance; }			
    }

    private SettingsRegistry settingsRegistry = new SettingsRegistry();
    public SettingsRegistry SettingsRegistry
    {
      get { return settingsRegistry; }
    }

		/// <summary>
		/// List of files to open when form is first shown.
		/// Set by Application
		/// </summary>
		private string[] commandLineArguments;
		public string[] CommandLineArguments
		{
			get { return commandLineArguments; }
			set { commandLineArguments = value; }
		}

    private MainForm mainForm;
    public MainForm MainForm
    {
      get { return mainForm; }
    }

    private GezelModelAnalysis gezelModelAnalysis;
    public GezelModelAnalysis GezelModelAnalysis
    {
      get { return gezelModelAnalysis; }
    }

    private GezelVhdlConversion gezelVhdlConversion;
    public GezelVhdlConversion GezelVhdlConversion
    {
      get { return gezelVhdlConversion; }      
    }

    //private MicroblazeCosimulation microblazeCosimulation;
    //public MicroblazeCosimulation MicroblazeCosimulation
    //{
    //  get { return microblazeCosimulation; }      
    //}


    private Project project;
    /// <summary>
    /// The project that is currently open 
    /// in the application
    /// </summary>
    /// <value></value>
    public Project Project
    {
      get { return project; }
      internal set 
      { 
        // unregister (if needed)
        if (project != value && project != null)
          ItemOpened -= project.ItemOpenedEventHandler;

        project = value;
       
        // register event handlers for open items
        ItemOpened += project.ItemOpenedEventHandler;
      }
    }

    private readonly List<ItemBase> openItems = new List<ItemBase>();
    /// <summary>
    /// The list of open items in 
    /// the application
    /// </summary>
    /// <value></value>
    public IList<ItemBase> OpenItems
    {
      get { return openItems.AsReadOnly(); }
    }

    private ItemBase selectedItem;

    public ItemBase SelectedItem
    {
      get { return selectedItem; }
      set 
      {
        if (selectedItem != value)
        {
          // invoked BEFORE the change 
          if (SelectedItemChanging != null)
            SelectedItemChanging(this, new SelectedItemChangedEventArgs(selectedItem));

          selectedItem = value;

          // invoked AFTER the change
          if (SelectedItemChanged != null)          
            SelectedItemChanged(this, new SelectedItemChangedEventArgs(selectedItem));          

          bool isNull = selectedItem != null;
          ActionBase.Actions[typeof(SaveSelectedItemAction)].Enabled = isNull && selectedItem.CanSave;
          ActionBase.Actions[typeof(SaveSelectedItemAsAction)].Enabled = isNull && selectedItem.CanSave;
        }
      }
    }

    /// <summary>
    /// Singleton constructor
    /// </summary>
    private Application()
    {      
    }

    /// <summary>
    /// This method initializes parts of the
    /// application which requires that the
    /// application instance has been set.
    /// </summary>
    private void Initialize()
    {
      gezelModelAnalysis = new GezelModelAnalysis();
      gezelVhdlConversion = new GezelVhdlConversion();
      //microblazeCosimulation = new MicroblazeCosimulation();

      // these calls has to be made before instancing the
      // mainform to render using the uxtheme.
      System.Windows.Forms.Application.EnableVisualStyles();
      //System.Windows.Forms.Application.e();

      this.mainForm = new MainForm();
      this.mainForm.SetLayoutControl(new Controls.WelcomeFillControl.WelcomeFillControl());

      //
      // GUI has been initialized, ok to call RegisterActions()
      //
      ActionBase.RegisterActions();
    }

    public void AddOpenItem(ItemBase item)
    {
      if (!openItems.Contains(item))
      {
        this.openItems.Add(item);
      }

      SelectedItem = item;

			if (ItemOpened != null)
				ItemOpened(this, new ItemOpenedOrClosedEventArgs(item));
    }

    public void RemoveOpenItem(ItemBase item)
    {
      if (openItems.Contains(item))
      {
        this.openItems.Remove(item);
      }

			if (ItemClosed != null)
				ItemClosed(this, new ItemOpenedOrClosedEventArgs(item));

      // try to set new selected item
      // from main tab control 
      TabPage tab = mainForm.MainTabControl.SelectedTab;
      if (tab != null)
      {
        SelectedItem = tab.Tag as ItemBase;
      }
      else
      {
        selectedItem = null;
      }
    }

    public bool CloseAllItems()
    {
			// create a copy of the openitems array 
			// needed since Close() will remove elements from the list 
			ItemBase[] items = openItems.ToArray();

      // cannot use 'foreach' here (openItems removed)
      for(int i = 0; i < items.Length; i++)      
        if (!items[i].Close())
          return false;

      return true;
    }
		
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    public static void Main(string[] args)
    {
			try
			{
				// save command line arguments
				Application.Instance.commandLineArguments = args;

		    Application.Instance.Initialize();

				System.Windows.Forms.Application.Run(Application.Instance.MainForm);
			}
			catch (Exception e)
			{
				Forms.ExceptionForm.Show(e);
			}
    }
  }
}
